package com.shop.util;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;

import java.beans.PropertyDescriptor;
import java.util.Map;

/**
 * 对象copy,区别于BeanUtilsBean.copyProperty()方法
 * 增加了值为null的情况不复制的逻辑
 **/
public class BeanCopyUtils {

    /**
     * 对象赋值,字段名称类型相同才会进行赋值操作
     *
     * @param dest 目标对象
     * @param orig 原来的对象
     * @throws Exception
     */
    public static void copyProperties(Object dest, Object orig) throws Exception {
        try {
            //实列出单列对象
            BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
            // Validate existence of the specified beans
            if (dest == null) {
                throw new IllegalArgumentException("No destination bean specified");
            }
            if (orig == null) {
                throw new IllegalArgumentException("No origin bean specified");
            }

            // Copy the properties, converting as necessary
            if (orig instanceof DynaBean) {
                final DynaProperty[] origDescriptors =
                        ((DynaBean) orig).getDynaClass().getDynaProperties();
                for (DynaProperty origDescriptor : origDescriptors) {
                    final String name = origDescriptor.getName();
                    // Need to check isReadable() for WrapDynaBean
                    // (see Jira issue# BEANUTILS-61)
                    if (beanUtilsBean.getPropertyUtils().isReadable(orig, name) &&
                            beanUtilsBean.getPropertyUtils().isWriteable(dest, name)) {
                        final Object value = ((DynaBean) orig).get(name);
                        beanUtilsBean.copyProperty(dest, name, value);
                    }
                }
            } else if (orig instanceof Map) {
                @SuppressWarnings("unchecked") final
                // Map properties are always of type <String, Object>
                        Map<String, Object> propMap = (Map<String, Object>) orig;
                for (final Map.Entry<String, Object> entry : propMap.entrySet()) {
                    final String name = entry.getKey();
                    if (beanUtilsBean.getPropertyUtils().isWriteable(dest, name)) {
                        beanUtilsBean.copyProperty(dest, name, entry.getValue());
                    }
                }
            } else /* if (orig is a standard JavaBean) */ {
                final PropertyDescriptor[] origDescriptors =
                        beanUtilsBean.getPropertyUtils().getPropertyDescriptors(orig);
                for (PropertyDescriptor origDescriptor : origDescriptors) {
                    final String name = origDescriptor.getName();
                    if ("class".equals(name)) {
                        continue; // No point in trying to set an object's class
                    }
                    if (beanUtilsBean.getPropertyUtils().isReadable(orig, name) &&
                            beanUtilsBean.getPropertyUtils().isWriteable(dest, name)) {
                        try {
                            final Object value =
                                    beanUtilsBean.getPropertyUtils().getSimpleProperty(orig, name);
                            if (null == value) {//增加逻辑,如果对象值为null，则不需要将null复制
                                continue;
                            }
                            beanUtilsBean.copyProperty(dest, name, value);
                        } catch (final NoSuchMethodException e) {
                            // Should not happen
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new Exception("~~~~~~~~bean copy Exception:" + e);
        }

    }
}
